use std::{rc::Rc, cell::RefCell, sync::Arc};

use crate::{native, rtda::{Frame, Object, DataType, heap::{string_pool, Class}, LocalVars}, instructions::base::{invoke_java_method, invoke_java_method_log}};

pub fn init() {
    native::register("java/lang/invoke/MethodHandle", "invokeExact", "([Ljava/lang/Object;)Ljava/lang/Object;", invoke_exact);

}

// public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
// ([Ljava/lang/Object;)Ljava/lang/Object;
fn invoke_exact(frame: Rc<RefCell<Frame>>) {
    let j_thread = frame.borrow().get_thread().lock().unwrap().get_j_thread();

    unsafe {
        let vars = frame.borrow().get_local_vars();
        // this
        let this = vars.borrow().get_this().unwrap();
        // params
        let arr = vars.borrow().get_ref(1).unwrap();
        let params = {&*arr}.get_array().get_refs();
        // for ele in params {
        //     if ele.is_some() {
        //         let e = ele.unwrap();
        //         let c = {&*e}.get_class();
        //         println!("{}", c.get_name());
        //     } else {
        //         println!("None");
        //     }
        // }

        let this_obj = { &*this };
        // dbg!(this_obj.get_class().get_name());
        // 231129 经测试slots有五个值[MethodType, LambdaForm, ?, ?, MemberName]（DirectMethodHandle）
        if let DataType::Slots(slots) = { &mut *this }.get_data_mut() {

            // TODO 231204 校验params参数与MethodType中的参数是否匹配
            // MethodType
            // let method_type = slots.get_ref(0).unwrap();
            // let mt_slots = match { &mut *method_type }.get_data_mut() {
            //     DataType::Slots(mt_slots) => mt_slots,
            //     _ => panic!()
            // };

            // member_name[class, methodName, methodType, flags, resolution]
            // 准备通过member_name获取要执行方法的class methodname methodtype，最终获取到要执行的方法
            let member_name = slots.get_ref(4).unwrap();
            // dbg!( {&*member_name}.get_class().get_name());
            // 获取要执行的方法。
            let mn_slots = match { &mut *member_name }.get_data_mut() {
                DataType::Slots(mn_slots) => mn_slots,
                _ => panic!()
            };
            // 方法类
            let class_obj = mn_slots.get_ref(0).unwrap();
            let class = {&*class_obj}.get_extra().unwrap().get_class();;
            // dbg!(class.get_name());
            // 方法名称
            let method_name = string_pool::rs_string(mn_slots.get_ref(1).unwrap());
            // dbg!(method_name.clone());
            // 方法descriptor
            let descriptor = method_type_to_descriptor(mn_slots.get_ref(2).unwrap(), None, j_thread);
            // dbg!(descriptor.clone());
            // 执行的方法。
            let method = class.get_method_any(&method_name, &descriptor).unwrap();
            // dbg!(method.get_name());
            // dbg!(method.get_descriptor());

            // 传递参数
            let mut vars = LocalVars::new_local_vars(method.get_max_locals());
            for i in 0..params.len() {
                vars.set_ref(i, params[i].clone())
            }



            // 执行，返回结果
            let stack = invoke_java_method(method.clone(), vars, None, j_thread);

            // 方法返回类型不为void返回结果。
            if !method.get_descriptor().ends_with('V') { 
                // TODO 231204 后续添加判断返回类型，不一定只返回object
                let obj = stack.borrow_mut().pop_ref();
                // dbg!(obj.is_some());
                let objc = &*obj.clone().unwrap();
                let occ = objc.get_class();
                // dbg!(occ.get_name());
                frame.borrow().get_operand_stack().borrow_mut().push_ref(obj);
            }






            // println!();
            // println!();

            // dbg!(slots.clone());
            // for i in 0..slots.len() {
            //     let o = slots.get_ref(i);
            //     if let Some(o) = o {
            //         dbg!({&*o}.get_class().get_name());
            //     } else {
            //         dbg!("none or 0");
            //     }
            // }
            
        }
    
        // panic!("cccabcddd");
        // frame.borrow().get_operand_stack().borrow_mut().push_ref(None);
    }

}

fn get_mamber_name() -> Option<*mut Object> {

    None
}


// 由 MethodHandleNatives.rs 复制过来的，后续可改为pub只用一个。
fn method_type_to_descriptor(mt: *mut Object, caller: Option<*mut Object>, j_thread: Option<*mut Object>) -> String {
    // 调用者class，为空用shim替代
    let caller_class = match caller {
        Some(obj) => unsafe{ &*obj }.get_extra().unwrap().get_class(),
        None => Arc::new(Class::new_shim())
    };

    let mt_class = unsafe{ &* mt }.get_class();
    // public String toMethodDescriptorString()
    let method = mt_class.get_instance_method("toMethodDescriptorString", "()Ljava/lang/String;").unwrap();
    
    // 创建新帧，执行方法，返回结果由shim_frame接收
    // let new_frame = Frame::new_frame(thread.clone(), method);
    let mut vars = LocalVars::new_local_vars(method.get_max_locals());
    // 实例方法self
    vars.set_ref(0, Some(mt));

    // 执行，返回结果
    let stack = invoke_java_method(method, vars, Some(caller_class), j_thread);

    let descriptor_obj = stack.borrow_mut().pop_ref();
    string_pool::rs_string(descriptor_obj.unwrap())
}